const fs = require('fs-extra');
const path = require('path');
const AdmZip = require('adm-zip');
const { DOMParser } = require('xmldom');
const chalk = require('chalk');

/**
 * 解压 EPUB 文件并提取所有 HTML 章节
 * @param {string} epubFilePath EPUB 文件路径
 * @param {string} outputDir 解压输出目录
 * @returns {Promise<{extractDir: string, htmlFiles: string[], opfDir: string, images: string[]}>}
 */
async function extractEpub(epubFilePath, outputDir) {
  // 1. 解压
  await fs.ensureDir(outputDir);
  const zip = new AdmZip(epubFilePath);
  zip.extractAllTo(outputDir, true);

  // 2. 查找 OPF 文件
  let opfPath = null;
  const containerPath = path.join(outputDir, 'META-INF', 'container.xml');
  if (await fs.pathExists(containerPath)) {
    const containerXml = await fs.readFile(containerPath, 'utf8');
    const containerDoc = new DOMParser().parseFromString(containerXml, 'text/xml');
    const rootfile = containerDoc.getElementsByTagName('rootfile')[0];
    if (rootfile) {
      opfPath = rootfile.getAttribute('full-path');
    }
  }

  let htmlFiles = [];
  let opfDir = '';
  let images = [];
  
  if (opfPath) {
    const opfAbsPath = path.join(outputDir, opfPath);
    if (await fs.pathExists(opfAbsPath)) {
      const opfXml = await fs.readFile(opfAbsPath, 'utf8');
      const opfDoc = new DOMParser().parseFromString(opfXml, 'text/xml');
      
      const manifest = opfDoc.getElementsByTagName('manifest')[0];
      const spine = opfDoc.getElementsByTagName('spine')[0];
      
      if (manifest && spine) {
        opfDir = path.dirname(opfPath);
        
        // 获取所有 HTML 文件映射
        const htmlMap = new Map();
        const imageMap = new Map();
        const items = manifest.getElementsByTagName('item');
        for (let i = 0; i < items.length; i++) {
          const item = items[i];
          const mediaType = item.getAttribute('media-type');
          const id = item.getAttribute('id');
          const href = item.getAttribute('href');
          
          if (mediaType === 'application/xhtml+xml' || mediaType === 'text/html') {
            htmlMap.set(id, href);
          } else if (mediaType && mediaType.startsWith('image/')) {
            // 收集图片文件
            const imagePath = path.join(opfDir, href);
            const relativePath = path.relative(outputDir, path.join(outputDir, imagePath));
            images.push(relativePath);
            imageMap.set(id, href);
          }
        }
        
        // 按 spine 顺序获取 HTML 文件
        const itemrefs = spine.getElementsByTagName('itemref');
        for (let i = 0; i < itemrefs.length; i++) {
          const itemref = itemrefs[i];
          const idref = itemref.getAttribute('idref');
          const href = htmlMap.get(idref);
          
          if (href) {
            const htmlPath = path.join(opfDir, href);
            const relativePath = path.relative(outputDir, path.join(outputDir, htmlPath));
            htmlFiles.push(relativePath);
          }
        }
      }
    }
  }

  // 3. 如果没找到章节，兜底查找所有 .html/.xhtml 文件
  if (htmlFiles.length === 0) {
    const allHtmlFiles = await findHtmlFiles(outputDir);
    htmlFiles = allHtmlFiles.map(file => path.relative(outputDir, file));
  }

  // 4. 如果没找到图片，兜底查找所有图片文件
  if (images.length === 0) {
    const allImageFiles = await findImageFiles(outputDir);
    images = allImageFiles.map(file => path.relative(outputDir, file));
  }

  return {
    extractDir: outputDir,
    htmlFiles: htmlFiles,
    opfDir: opfDir,
    images: images
  };
}

/**
 * 处理 HTML 文件中的图片路径
 * @param {string} htmlContent HTML 内容
 * @param {string} htmlFilePath HTML 文件路径
 * @param {string} extractDir 解压目录
 * @returns {string} 处理后的 HTML 内容
 */
function processImagePaths(htmlContent, htmlFilePath, extractDir) {
  // 将相对路径转换为相对于合并HTML的路径
  const htmlDir = path.dirname(htmlFilePath);
  let processedCount = 0;

  // 处理 img 标签的 src 属性
  htmlContent = htmlContent.replace(
    /<img([^>]*?)src=["']([^"']+)["']([^>]*?)>/gi,
    (match, before, src, after) => {
      // 如果已经是 http(s):// 或 data: URL，跳过处理
      if (src.startsWith('http://') || src.startsWith('https://') || src.startsWith('data:')) {
        return match;
      }
      // 只保留相对路径（如 images/xxx.png）
      let relativePath = src;
      // 如果是绝对路径（/images/xxx.png），去掉开头的 /
      if (relativePath.startsWith('/')) {
        relativePath = relativePath.substring(1);
      }
      // 快速检查是否为图片文件
      if (!/\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(relativePath)) {
        return match; // 不是图片文件，保持原样
      }
      processedCount++;
      return `<img${before}src="${relativePath}"${after}>`;
    }
  );

  // 处理 CSS 中的背景图片
  htmlContent = htmlContent.replace(
    /background-image:\s*url\(['"]?([^'")\s]+)['"]?\)/gi,
    (match, url) => {
      if (url.startsWith('http://') || url.startsWith('https://') || url.startsWith('data:')) {
        return match;
      }
      let relativePath = url;
      if (relativePath.startsWith('/')) {
        relativePath = relativePath.substring(1);
      }
      // 快速检查是否为图片文件
      if (!/\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(relativePath)) {
        return match; // 不是图片文件，保持原样
      }
      processedCount++;
      return `background-image: url("${relativePath}")`;
    }
  );

  if (processedCount > 0) {
    console.log(chalk.green(`✅ 处理了 ${processedCount} 个图片路径`));
  }

  return htmlContent;
}

// 递归查找 .html/.xhtml 文件
async function findHtmlFiles(dir) {
  let results = [];
  const list = await fs.readdir(dir);
  for (const file of list) {
    const filePath = path.join(dir, file);
    const stat = await fs.stat(filePath);
    if (stat.isDirectory()) {
      results = results.concat(await findHtmlFiles(filePath));
    } else if (file.toLowerCase().endsWith('.html') || file.toLowerCase().endsWith('.xhtml')) {
      results.push(filePath);
    }
  }
  return results;
}

// 递归查找图片文件
async function findImageFiles(dir) {
  let results = [];
  const list = await fs.readdir(dir);
  for (const file of list) {
    const filePath = path.join(dir, file);
    const stat = await fs.stat(filePath);
    if (stat.isDirectory()) {
      results = results.concat(await findImageFiles(filePath));
    } else if (/\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file)) {
      results.push(filePath);
    }
  }
  return results;
}

module.exports = {
  extractEpub,
  processImagePaths
}; 